home *** CD-ROM | disk | FTP | other *** search
/ Scene 96 / Scene 96 International Edition (Zyklop Software) (Disc 2) (1997).iso / misc / coding / cp2dekit / samples / devpsb.cpp < prev    next >
C/C++ Source or Header  |  1996-12-29  |  12KB  |  662 lines

  1. //***************************************************************************
  2. //
  3. // this file is (c) '94-'96 Niklas Beisert
  4. //
  5. // this file is part of the cubic player development kit.
  6. // you may only use/modify/spread this file under the terms stated
  7. // in the cubic player development kit accompanying documentation.
  8. //
  9. //***************************************************************************
  10.  
  11. //cp.ini
  12. //[sound]
  13. //  playerdevices=devpSB
  14. //[devpSB]
  15. //  link=devpsb
  16. //  driver=_plrSoundBlaster
  17. //  addprocs=_plrSBAdd
  18. //  handle=1
  19. //  sbrevstereo=off ;// some sb pros reverse stereo...
  20.  
  21. // player sound device example
  22.  
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <dos.h>
  26. #include <ctype.h>
  27. #include <conio.h>
  28. #include "irq.h"
  29. #include "dma.h"
  30. #include "ss.h"
  31. #include "player.h"
  32.  
  33. #define SS_SB_REVSTEREO 1
  34.  
  35.  
  36. extern "C" extern sounddevice plrSoundBlaster;
  37.  
  38. static signed short sbPort;
  39. static signed char sbIRQ;
  40. static signed char sbDMA;
  41. static signed char sbDMA16;
  42. static signed char sbUseVer;
  43. static char rightirq;
  44.  
  45. static unsigned char getcfg()
  46. {
  47.   sbPort=-1;
  48.   sbIRQ=-1;
  49.   sbDMA=-1;
  50.   sbDMA16=-1;
  51.   sbUseVer=-1;
  52.   char *s=getenv("BLASTER");
  53.   if (!s)
  54.     return 0;
  55.   while (1)
  56.   {
  57.     while (isspace(*s))
  58.       s++;
  59.     if (!*s)
  60.       break;
  61.     switch (*s++)
  62.     {
  63.     case 'a': case 'A':
  64.       sbPort=strtoul(s, 0, 16);
  65.       break;
  66.     case 'i': case 'I':
  67.       sbIRQ=strtoul(s, 0, 10);
  68.       break;
  69.     case 'd': case 'D':
  70.       sbDMA=strtoul(s, 0, 10);
  71.       break;
  72.     case 'h': case 'H':
  73.       sbDMA16=strtoul(s, 0, 10);
  74.       break;
  75.     case 't': case 'T':
  76.       sbUseVer=strtoul(s, 0, 10);
  77.       switch (sbUseVer)
  78.       {
  79.       case 6: sbUseVer=4; break;
  80.       case 2: case 4: sbUseVer=3; break;
  81.       case 3: sbUseVer=2; break;
  82.       case 1: sbUseVer=1; break;
  83.       default: sbUseVer=-1;
  84.       }
  85.       break;
  86.     }
  87.     while (!isspace(*s)&&*s)
  88.       s++;
  89.   }
  90.   return 1;
  91. }
  92.  
  93. static unsigned char inpSB(unsigned char p)
  94. {
  95.   return inp(sbPort+p);
  96. }
  97.  
  98. static void outpSB(unsigned char p, unsigned char v)
  99. {
  100.   outp(sbPort+p,v);
  101. }
  102.  
  103. static void outSB(unsigned char v)
  104. {
  105.   while (inpSB(0xC)&0x80);
  106.   outpSB(0xC,v);
  107. }
  108.  
  109. static unsigned char inSB()
  110. {
  111.   while (!(inpSB(0xE)&0x80));
  112.   return inpSB(0xA);
  113. }
  114.  
  115. static void initSB()
  116. {
  117.   outpSB(0x6,1);
  118.   inpSB(0x6);
  119.   inpSB(0x6);
  120.   inpSB(0x6);
  121.   inpSB(0x6);
  122.   inpSB(0x6);
  123.   inpSB(0x6);
  124.   inpSB(0x6);
  125.   inpSB(0x6);
  126.   outpSB(0x6,0);
  127. }
  128.  
  129. static void initSBp()
  130. {
  131.   outpSB(0x6,1);
  132.   delay(100);
  133.   outpSB(0x6,0);
  134.   delay(100);
  135. }
  136.  
  137. static setrateSB(unsigned char r)
  138. {
  139.   outSB(0x40);
  140.   outSB(r);
  141. }
  142.  
  143. static void resetSB()
  144. {
  145.   inpSB(0xE);
  146. }
  147.  
  148. static void resetSB16()
  149. {
  150.   inpSB(0xF);
  151. }
  152.  
  153. static void spkronSB()
  154. {
  155.   outSB(0xD1);
  156. }
  157.  
  158. static void spkroffSB()
  159. {
  160.   outSB(0xD3);
  161. }
  162.  
  163. static void writeMixer(unsigned char p, unsigned char v)
  164. {
  165.   outpSB(0x4, p);
  166.   outpSB(0x5, v);
  167. }
  168.  
  169. static unsigned char readMixer(unsigned char p)
  170. {
  171.   outpSB(0x4, p);
  172.   return inpSB(0x5);
  173. }
  174.  
  175. static void test()
  176. {
  177.   rightirq=1;
  178. }
  179.  
  180. static char testPort(unsigned short port, int delay)
  181. {
  182.   sbPort=port;
  183.   if (delay)
  184.     initSBp();
  185.   else
  186.     initSB();
  187.   int i;
  188.   for (i=0; i<1000; i++)
  189.     if (inpSB(0xE)&0x80)
  190.       return inpSB(0xA)==0xAA;
  191.   return 0;
  192. }
  193.  
  194. static char testirq(unsigned char irq)
  195. {
  196.   irqInit(irq, test, 0);
  197.  
  198.   initSB();
  199.   setrateSB(0xD3);
  200.  
  201.   rightirq=0;
  202.  
  203.   outSB(0x80);
  204.   outSB(0x03);
  205.   outSB(0x00);
  206.   for (unsigned short i=0; i!=0xFFFF; i++)
  207.     if (rightirq)
  208.       break;
  209.  
  210.   irqClose();
  211.  
  212.   initSB();
  213.   resetSB();
  214.  
  215.   return rightirq;
  216. }
  217.  
  218. static char testdma(unsigned char irq, unsigned char dma)
  219. {
  220.   outp(0x0A,4);
  221.   outp(0x0A,5);
  222.   outp(0x0A,7);
  223.  
  224.   irqInit(irq, test, 0);
  225.   dmaStart(dma, 0, 10, 0x48);
  226.  
  227.   initSB();
  228.   setrateSB(0xD3);
  229.  
  230.   rightirq=0;
  231.  
  232.   outSB(0x14);
  233.   outSB(0x03);
  234.   outSB(0x00);
  235.   for (unsigned short i=0; i!=0xFFFF; i++)
  236.     if (rightirq)
  237.       break;
  238.   irqClose();
  239.   dmaStop();
  240.  
  241.   initSB();
  242.   resetSB();
  243.  
  244.   return rightirq;
  245. }
  246.  
  247. static char testdma16(unsigned char irq, unsigned char dma)
  248. {
  249.   outp(0x0A,4);
  250.   outp(0x0A,5);
  251.   outp(0x0A,7);
  252.   outp(0xD4,5);
  253.   outp(0xD4,6);
  254.   outp(0xD4,7);
  255.  
  256.   irqInit(irq, test, 0);
  257.   dmaStart(dma, 0, 2, 0x48);
  258.  
  259.   initSB();
  260.   setrateSB(0xEA);
  261.  
  262.   rightirq=0;
  263.  
  264.   outSB(0xB6);
  265.   outSB(0x10);
  266.   outSB(0x00);
  267.   outSB(0x00);
  268.   for (unsigned i=0; i!=0xFFFF; i++)
  269.     if (rightirq)
  270.       break;
  271.   irqClose();
  272.   dmaStop();
  273.  
  274.   initSB();
  275.   resetSB16();
  276.  
  277.   return rightirq;
  278. }
  279.  
  280. static unsigned short getVersion()
  281. {
  282.   outSB(0xE1);
  283.   while(1)
  284.   {
  285.     unsigned char verhi=inSB();
  286.     if (verhi==0xAA)
  287.       continue;
  288.     return ((unsigned short)verhi<<8)+inSB();
  289.   }
  290. }
  291.  
  292.  
  293.  
  294. static long playpos;
  295. static long buflen;
  296. static int lastpos=17977;
  297. static void (*playproc)();
  298. static int regengetpos()
  299. {
  300.   int p=dmaGetBufPos();
  301.   if (p==lastpos)
  302.   {
  303.     playproc();
  304.     irqReInit();
  305.   }
  306.   lastpos=p;
  307.   return p;
  308. }
  309.  
  310. static void advance(int pos)
  311. {
  312.   playpos+=(pos-(playpos%buflen)+buflen)%buflen;
  313. }
  314.  
  315. static void sb1Player()
  316. {
  317.   resetSB();
  318.   outSB(0x14);
  319.   outSB(0xFF);
  320.   outSB(0xFF);
  321. }
  322.  
  323. static void sb2proPlayerHS()
  324. {
  325.   resetSB();
  326.   outSB(0x91);
  327. }
  328.  
  329. static void sb16Player8()
  330. {
  331.   resetSB();
  332.   outSB(0x45);
  333. }
  334.  
  335. static void sb16Player16()
  336. {
  337.   outSB(0x47);
  338.   resetSB16();
  339. }
  340.  
  341. static int sbRate;
  342. static unsigned char sbTimerConst;
  343. static unsigned char sbStereo;
  344. static unsigned char sb16Bit;
  345. static unsigned char sbSignedOut;
  346. static unsigned char revstereo;
  347. static __segment dmabufsel;
  348.  
  349. static void sbSetOptions(int rate, int opt)
  350. {
  351.   switch (sbUseVer)
  352.   {
  353.   case 1: case 2:
  354.     opt&=~(PLR_STEREO|PLR_16BIT|PLR_SIGNEDOUT);
  355.     break;
  356.   case 3:
  357.     opt&=~(PLR_16BIT|PLR_SIGNEDOUT);
  358.     break;
  359.   }
  360.   if (revstereo)
  361.     opt^=PLR_REVERSESTEREO;
  362.   sbStereo=!!(opt&PLR_STEREO);
  363.   sb16Bit=!!(opt&PLR_16BIT);
  364.   sbSignedOut=!!(opt&PLR_SIGNEDOUT);
  365.  
  366.   unsigned long rt=rate;
  367.   if ((sbUseVer==3)&&sbStereo)
  368.     rt<<=1;
  369.  
  370.   if (rt<4000)
  371.     rt=4000;
  372.   if (sbUseVer==4)
  373.     if (rt<5000)
  374.       rt=5000;
  375.   if ((sbUseVer==2)||(sbUseVer==3))
  376.     if (rt<8000)
  377.       rt=8000;
  378.  
  379.   if (rt>45454)
  380.     rt=45454;
  381.   if ((sbUseVer==2)||(sbUseVer==3))
  382.     if (rt>43478)
  383.       rt=43478;
  384.   if ((sbUseVer==1))
  385.     if (rt>22222)
  386.       rt=22222;
  387.  
  388.   sbTimerConst=256-1000000/rt;
  389.   rate=1000000/(256-sbTimerConst);
  390.  
  391.   if ((sbUseVer==3)&&sbStereo)
  392.     rate>>=1;
  393.  
  394.   sbRate=rate;
  395.   plrRate=rate;
  396.   plrOpt=opt;
  397. }
  398.  
  399. long muldiv64(long, long, long);
  400. #pragma aux muldiv64 parm [eax] [edx] [ecx] = "imul edx" "idiv ecx"
  401.  
  402. static long gettimer()
  403. {
  404.   return muldiv64(playpos+(dmaGetBufPos()-playpos%buflen+buflen)%buflen, 65536, sbRate<<(sbStereo+sb16Bit));
  405. }
  406.  
  407. void memsetd(void *, long, int);
  408. #pragma aux memsetd parm [edi] [eax] [ecx] = "rep stosd"
  409.  
  410. static int sbPlay(void *&buf, int &len)
  411. {
  412.   buf=(unsigned char*)dmaAlloc(len, dmabufsel);
  413.   if (!buf)
  414.     return 0;
  415.   memsetd(buf, (plrOpt&PLR_SIGNEDOUT)?0:(plrOpt&PLR_16BIT)?0x80008000:0x80808080, len>>2);
  416.  
  417.   initSBp();
  418.   resetSB();
  419.   resetSB16();
  420.   setrateSB(sbTimerConst);
  421.   setrateSB(sbTimerConst);
  422.   spkronSB();
  423.  
  424.   switch (sbUseVer)
  425.   {
  426.   case 1:
  427.     playproc=sb1Player;
  428.     break;
  429.   case 2: case 3:
  430.     playproc=sb2proPlayerHS;
  431.     break;
  432.   case 4:
  433.     playproc=sb16Bit?sb16Player16:sb16Player8;
  434.     break;
  435.   }
  436.  
  437.   irqInit(sbIRQ, playproc, 0);
  438.   dmaStart(sb16Bit?sbDMA16:sbDMA, buf, len, 0x58);
  439.  
  440.   switch (sbUseVer)
  441.   {
  442.   case 1:
  443.     outSB(0x14);
  444.     outSB(0xFF);
  445.     outSB(0xFF);
  446.     break;
  447.   case 2: case 3:
  448.     outSB(0x48);
  449.     outSB(0xFF);
  450.     outSB(0xFF);
  451.     outSB(0x91);
  452.     if (sbUseVer==3)
  453.       writeMixer(0xE, readMixer(0xE)&~2|(sbStereo?0x22:0x20));
  454.     break;
  455.   case 4:
  456.     outSB(sb16Bit?0xB6:0xC6);
  457.     outSB((sbStereo?0x20:0x00)|(sbSignedOut?0x10:0x00));
  458.     outSB(0xFC);
  459.     outSB(0xFF);
  460.     break;
  461.   }
  462.  
  463.   buflen=len;
  464.   playpos=0;
  465.   plrGetBufPos=regengetpos;
  466.   plrGetPlayPos=regengetpos;
  467.   plrAdvanceTo=advance;
  468.   plrGetTimer=gettimer;
  469.  
  470.   return 1;
  471. }
  472.  
  473. static void sbStop()
  474. {
  475.   irqClose();
  476.   dmaStop();
  477.   initSBp();
  478.   resetSB();
  479.   resetSB16();
  480.   dmaFree(dmabufsel);
  481. }
  482.  
  483.  
  484.  
  485. static int sbInit(const deviceinfo &card)
  486. {
  487.   if (!testPort(card.port, 1))
  488.     return 0;
  489.   resetSB();
  490.   resetSB16();
  491.  
  492.   revstereo=!!(card.opt&SS_SB_REVSTEREO);
  493.  
  494.   sbPort=card.port;
  495.   sbIRQ=card.irq;
  496.   sbDMA=card.dma;
  497.   sbDMA16=card.dma2;
  498.   unsigned char ver=getVersion()>>8;
  499.   if (card.subtype==-1)
  500.     sbUseVer=ver;
  501.   else
  502.     sbUseVer=card.subtype;
  503.   if (sbUseVer>ver)
  504.     return 0;
  505.   if ((sbUseVer==3)&&(ver==4))
  506.     return 0;
  507.  
  508. /*
  509.   if (!testirq(sbIRQ))
  510.     return 0;
  511.   if (!testdma(sbIRQ, sbDMA))
  512.     return 0;
  513.   if (sbUseVer==4)
  514.     if (!testdma16(sbIRQ, sbDMA16))
  515.       return 0;
  516. */
  517.  
  518.   plrSetOptions=sbSetOptions;
  519.   plrPlay=sbPlay;
  520.   plrStop=sbStop;
  521.  
  522.   return 1;
  523. }
  524.  
  525. static void sbClose()
  526. {
  527.   plrPlay=0;
  528. }
  529.  
  530. static int sbDetect(deviceinfo &card)
  531. {
  532.   getcfg();
  533.   if (card.port!=-1)
  534.     sbPort=card.port;
  535.   if (card.irq!=-1)
  536.     sbIRQ=card.irq;
  537.   if (card.dma!=-1)
  538.     sbDMA=card.dma;
  539.   if (card.dma2!=-1)
  540.     sbDMA16=card.dma2;
  541.   if (card.subtype!=-1)
  542.     sbUseVer=card.subtype;
  543.  
  544.   int i;
  545.   if (sbPort==-1)
  546.   {
  547.     unsigned short ports[]={0x220, 0x240, 0x260, 0x280, 0x210, 0x230, 0x250};
  548.     for (i=0; i<(sizeof(ports)>>1); i++)
  549.       if (testPort(ports[i],0))
  550.         break;
  551.     if (i==(sizeof(ports)>>1))
  552.       return 0;
  553.     sbPort=ports[i];
  554.   }
  555.   else
  556.     if (!testPort(sbPort, 0))
  557.       return 0;
  558.  
  559.   unsigned short ver=getVersion()>>8;
  560.   if (sbUseVer==-1)
  561.     sbUseVer=ver;
  562.   if ((sbUseVer<1)||(sbUseVer>4))
  563.     return 0;
  564.  
  565.   if (ver<sbUseVer)
  566.     return 0;
  567.   if ((ver==4)&&(sbUseVer==3))
  568.     return 0;
  569.  
  570.   if (sbIRQ==-1)
  571.   {
  572.     if (sbUseVer!=4)
  573.     {
  574.       unsigned char irqs[]={7, 5, 2, 3, 10};
  575.       for (i=0; i<sizeof(irqs); i++)
  576.         if (testirq(irqs[i]))
  577.           break;
  578.       if (i==sizeof(irqs))
  579.         return 0;
  580.       sbIRQ=irqs[i];
  581.     }
  582.     else
  583.     {
  584.       unsigned char a=readMixer(0x80);
  585.       if (!(a&0x0F))
  586.         return 0;
  587.       sbIRQ=(a&2)?5:(a&4)?7:(a&1)?2:10;
  588.     }
  589.   }
  590. //  else
  591. //    if (!testirq(sbIRQ))
  592. //      return 0;
  593.  
  594.   if (sbDMA==-1)
  595.   {
  596.     if (sbUseVer!=4)
  597.     {
  598.       unsigned char dmas[]={1, 0, 3};
  599.       for (i=0; i<sizeof(dmas); i++)
  600.         if (testdma(sbIRQ, dmas[i]))
  601.           break;
  602.       if (i==sizeof(dmas))
  603.         return 0;
  604.       sbDMA=dmas[i];
  605.     }
  606.     else
  607.     {
  608.       unsigned char b=readMixer(0x81);
  609.       if (!(b&0x0B))
  610.         return 0;
  611.       sbDMA=(b&2)?1:(b&1)?0:3;
  612.     }
  613.   }
  614. //  else
  615. //    if (!testdma(sbIRQ, sbDMA))
  616. //      return 0;
  617.  
  618.   if (sbUseVer==4)
  619.   {
  620.     if (sbDMA16==-1)
  621.     {
  622.       unsigned char b=readMixer(0x81);
  623.       if (!(b&0x0B))
  624.         return 0;
  625.       sbDMA16=(b&0x20)?5:(b&0x40)?6:(b&0x80)?7:sbDMA;
  626.     }
  627. //    else
  628. //      if (!testdma16(sbIRQ, sbDMA16))
  629. //        return 0;
  630.   }
  631.   else
  632.     sbDMA16=-1;
  633.  
  634.   card.dev=&plrSoundBlaster;
  635.   card.port=sbPort;
  636.   card.port2=-1;
  637.   card.irq=sbIRQ;
  638.   card.irq2=-1;
  639.   card.dma=sbDMA;
  640.   card.dma2=sbDMA16;
  641.   card.subtype=sbUseVer;
  642.   card.mem=0;
  643.   card.chan=(card.subtype<3)?1:2;
  644.  
  645.   return 1;
  646. }
  647.  
  648. extern "C" sounddevice plrSoundBlaster={SS_PLAYER, "SoundBlaster", sbDetect, sbInit, sbClose};
  649.  
  650. #include "devigen.h"
  651. #include "psetting.h"
  652.  
  653. static unsigned long sbGetOpt(const char *sec)
  654. {
  655.   unsigned long opt=0;
  656.   if (cfGetProfileBool(sec, "sbrevstereo", 0, 0))
  657.     opt|=SS_SB_REVSTEREO;
  658.   return opt;
  659. }
  660.  
  661. extern "C" devaddstruct plrSBAdd = {sbGetOpt, 0, 0, 0};
  662.